#include "ccd290.h"

int init_waveform_config_default( waveform_config *wf_cfg ){

    wf_cfg->N_ROW               = 100;
    wf_cfg->N_COL               = 1250;
    wf_cfg->SAMP_NUM_PER_REG    = 100;

    wf_cfg->REG_CLK_NUM         = -1;
    wf_cfg->LEN                 = -1;

    wf_cfg->WAVE_TYPE           = _CCD_OSX_;
    wf_cfg->OS_NUM              = 1;
    wf_cfg->IMG_PHASE           = 1;
    wf_cfg->REG_PHASE           = 1;

    wf_cfg->S1_idx0             = -1;
    wf_cfg->S1_idx1             = -1;

    wf_cfg->S2_idx0             = -1;
    wf_cfg->S2_idx1             = -1;

    wf_cfg->S3_idx0             = -1;
    wf_cfg->S3_idx1             = -1;

    wf_cfg->S4_idx0             = -1;
    wf_cfg->S4_idx1             = -1;

    wf_cfg->S5_idx0             = -1;
    wf_cfg->S5_idx1             = -1;

    wf_cfg->S5_idx0             = -1;
    wf_cfg->S6_idx1             = -1;

    wf_cfg->AD_REF_FREQ         = 50.;    // MHz
    wf_cfg->AD_CLK_DIV          = 3;
    wf_cfg->AD_CLK_PERIOD       = 0.06;    // us
    wf_cfg->V_TRANS_PERIOD      = 300;    // us
    wf_cfg->REG_CLK_PERIOD      = 6;    // us


    sprintf(wf_cfg->out_root, "wave_tmp");
    sprintf(wf_cfg->out_dir, "./");
    
    sprintf(wf_cfg->outfile, "");

    return 0;
}

int init_waveform_config( waveform_config *wf_cfg, char *inifile ){

    dictionary *ini;

    ini = iniparser_load(inifile);

    wf_cfg->N_ROW               = iniparser_getint( ini, "WAVEFORM:N_ROW", 100 );
    wf_cfg->N_COL               = iniparser_getint( ini, "WAVEFORM:N_COL", 1250 );
    wf_cfg->SAMP_NUM_PER_REG    = iniparser_getint( ini, "WAVEFORM:SAMP_NUM_PER_REG", 100 );
    wf_cfg->WAVE_TYPE           = iniparser_getint( ini, "WAVEFORM:WAVE_TYPE", _CCD_OSX_ );
    wf_cfg->OS_NUM              = iniparser_getint( ini, "WAVEFORM:OS_NUM", 1 );
    wf_cfg->IMG_PHASE           = iniparser_getint( ini, "WAVEFORM:IMG_PHASE", 1 );
    wf_cfg->REG_PHASE           = iniparser_getint( ini, "WAVEFORM:REG_PHASE", 1 );

    wf_cfg->verbose             = iniparser_getint( ini, "WAVEFORM:VERBOSE", 0 );

    if( (wf_cfg->WAVE_TYPE != _CCD_OSX_) &&
        (wf_cfg->WAVE_TYPE != _V_DRIVE_) &&
        (wf_cfg->WAVE_TYPE != _H_DRIVE_)  ) {
        printf("(%s:L:%d) wrong WAVE_TYPE: %d\n", __FILE__, __LINE__, wf_cfg->WAVE_TYPE);
        exit(0);
    }

//  AD_REF_FREQ的值与读出板上AD芯片的驱动时钟有关系，对V5版而言是50MHz
    wf_cfg->AD_REF_FREQ      = iniparser_getdouble( ini,"WAVEFORM:AD_REF_FREQ", 50 );

//  与AD9249采样频率的参数配置有关系
    wf_cfg->AD_CLK_DIV       = iniparser_getint( ini,"WAVEFORM:AD_CLK_DIV", 3 );

//  行转移周期(单位:微秒)
    wf_cfg->V_TRANS_PERIOD   = iniparser_getdouble( ini, "WAVEFORM:V_TRANS_PERIOD", 300 );


//  实际AD采样周期
    wf_cfg->AD_CLK_PERIOD    = 1. / (wf_cfg->AD_REF_FREQ / wf_cfg->AD_CLK_DIV);
    wf_cfg->REG_CLK_PERIOD   = wf_cfg->AD_CLK_PERIOD * wf_cfg->SAMP_NUM_PER_REG;

    printf("> (debug) wf_cfg->REG_CLK_PERIOD = %g\n", wf_cfg->REG_CLK_PERIOD);

    wf_cfg->S1_idx0 = 0;
    wf_cfg->S1_idx1 = wf_cfg->S1_idx0 + 1 * wf_cfg->SAMP_NUM_PER_REG;
    
    wf_cfg->S2_idx0 = wf_cfg->S1_idx1;
    wf_cfg->S2_idx1 = wf_cfg->S2_idx0 + wf_cfg->N_COL * wf_cfg->SAMP_NUM_PER_REG;

    wf_cfg->S3_idx0 = wf_cfg->S2_idx1;
    wf_cfg->S3_idx1 = wf_cfg->S3_idx0 + 1 * wf_cfg->SAMP_NUM_PER_REG;

    wf_cfg->S4_idx0 = wf_cfg->S3_idx1;
    wf_cfg->S4_idx1 = wf_cfg->S4_idx0 + 1 * wf_cfg->SAMP_NUM_PER_REG;

    wf_cfg->S5_idx0 = wf_cfg->S4_idx1;
    // wf_cfg->S5_idx1 = wf_cfg->S5_idx0 + (wf_cfg->V_TRANS_PERIOD / wf_cfg->AD_CLK_PERIOD);
    wf_cfg->S5_idx1 = wf_cfg->S5_idx0 + wf_cfg->V_TRANS_PERIOD * wf_cfg->SAMP_NUM_PER_REG;

    wf_cfg->S6_idx0 = wf_cfg->S5_idx1;
    wf_cfg->S6_idx1 = wf_cfg->S6_idx0 + 1 * wf_cfg->SAMP_NUM_PER_REG;;

//	计算所保存的16bits数据对应的总数目
    wf_cfg->REG_CLK_NUM	= wf_cfg->S6_idx1 * wf_cfg->N_ROW;
    wf_cfg->LEN	        = wf_cfg->REG_CLK_NUM;

//  读取结果输出的文件名root和输出目录
    char *out_root = (char*)iniparser_getstring(ini, "ANALYSIS:OUT_ROOT", "wave_tmp");
    char *out_dir  = (char*)iniparser_getstring(ini, "ANALYSIS:OUT_DIR", "./");

    sprintf(wf_cfg->out_root, "%s", out_root);
    sprintf(wf_cfg->out_dir, "%s", out_dir);


//  释放ini的内存
    iniparser_freedict(ini);

//  打印配置信息
    print_waveform_config( wf_cfg );

    // exit(0);    // debug

    return 0;
}

int print_waveform_config( waveform_config *wf_cfg ){

    if( wf_cfg->verbose != 1 )
        return 0;
    
    printf("/******************** waveform_config *********************/\n");
    
    printf("# N_ROW                 = %10d\n", wf_cfg->N_ROW);
    printf("# N_COL                 = %10d\n", wf_cfg->N_COL);
    printf("# SAMP_NUM_PER_REG      = %10d\n", wf_cfg->SAMP_NUM_PER_REG);
    printf("# WAVE_TYPE             = %10d\n", wf_cfg->WAVE_TYPE);

    if( wf_cfg->WAVE_TYPE == _CCD_OSX_ ){
        printf("@ OS_NUM                = %10d\n", wf_cfg->OS_NUM);
    } else if( wf_cfg->WAVE_TYPE == _V_DRIVE_ ){
        printf("@ IMG_PHASE             = %10d\n", wf_cfg->IMG_PHASE);
    } else if( wf_cfg->WAVE_TYPE == _H_DRIVE_ ){
        printf("@ REG_PHASE             = %10d\n", wf_cfg->REG_PHASE);
    }

    printf("# REG_CLK_NUM           = %10d\n", wf_cfg->REG_CLK_NUM);
    printf("# LEN                   = %10d\n", wf_cfg->LEN);

    printf("# AD_REF_FREQ           = %10.5f MHz\n", wf_cfg->AD_REF_FREQ);
    printf("# AD_CLK_DIV            = %10d\n", wf_cfg->AD_CLK_DIV);
    printf("# AD_CLK_PERIOD         = %10.5f us\n", wf_cfg->AD_CLK_PERIOD);
    // printf("# V_TRANS_PERIOD        = %10.5f us\n", wf_cfg->V_TRANS_PERIOD);
    printf("# V_TRANS_PERIOD        = %10.5f (# of reg_clk)\n", wf_cfg->V_TRANS_PERIOD);
    printf("# REG_CLK_PERIOD        = %10.5f us\n", wf_cfg->REG_CLK_PERIOD);
    
    printf("# S1_idx0               = %10d [reg_pre state]\n", wf_cfg->S1_idx0);
    printf("# S1_idx1               = %10d [reg_pre state]\n", wf_cfg->S1_idx1);

    printf("# S2_idx0               = %10d [reg state]\n", wf_cfg->S2_idx0);
    printf("# S2_idx1               = %10d [reg_state]\n", wf_cfg->S2_idx1);

    printf("# S3_idx0               = %10d [reg_post state]\n", wf_cfg->S3_idx0);
    printf("# S3_idx1               = %10d [reg_post state]\n", wf_cfg->S3_idx1);

    printf("# S4_idx0               = %10d [lt_pre state]\n", wf_cfg->S4_idx0);
    printf("# S4_idx1               = %10d [lt_pre state]\n", wf_cfg->S4_idx1);

    printf("# S5_idx0               = %10d [lt state]\n", wf_cfg->S5_idx0);
    printf("# S5_idx1               = %10d [lt state]\n", wf_cfg->S5_idx1);

    printf("# S6_idx0               = %10d [lt_post state]\n", wf_cfg->S6_idx0);
    printf("# S6_idx1               = %10d [lt_post state]\n", wf_cfg->S6_idx1);

    printf("# out_root              = %s\n", wf_cfg->out_root);
    printf("# out_dir               = %s\n", wf_cfg->out_dir);

    printf("/**********************************************************/\n");

    return 0;
}
